﻿using System;
using System.Drawing;

namespace Simple3DRedactor.Domain
{
    [Serializable]
    public struct Material
    {
        public event Action Change;
        private void OnChange()
        {
            if (Change != null) Change();
        }

        private Color _ambient;
        public Color Ambient
        {
            get { return _ambient; }
            set
            {
                if (_ambient != value)
                {
                    _ambient = value;
                    OnChange();
                }
            }
        }

        private Color _diffuse;
        public Color Diffuse
        {
            get { return _diffuse; }
            set
            {
                if (_diffuse != value)
                {
                    _diffuse = value;
                    OnChange();
                }
            }
        }

        private Color _specular;
        public Color Specular
        {
            get { return _specular; }
            set
            {
                if (_specular != value)
                {
                    _specular = value;
                    OnChange();
                }
            }
        }

        private float _shininess;
        public float Shininess
        {
            get { return _shininess; }
            set
            {
                if (Math.Abs(_shininess - value) > float.Epsilon)
                {
                    _shininess = value;
                    OnChange();
                }
            }
        }

        private Color _emission;
        public Color Emission
        {
            get { return _emission; }
            set
            {
                if (_emission != value)
                {
                    _emission = value;
                    OnChange();
                }
            }
        }

        public static bool operator == (Material m1, Material m2)
        {
            return m1.Equals(m2);
        }

        public static bool operator !=(Material m1, Material m2)
        {
            return !(m1 == m2);
        }

        public bool Equals(Material other)
        {
            return other.Ambient.Equals(Ambient) && other.Diffuse.Equals(Diffuse) && other.Specular.Equals(Specular) && 
                other.Shininess.Equals(Shininess) && other.Emission.Equals(Emission);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            return obj is Material && Equals((Material) obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                var result = Ambient.GetHashCode();
                result = (result*397) ^ Diffuse.GetHashCode();
                result = (result*397) ^ Specular.GetHashCode();
                result = (result*397) ^ Shininess.GetHashCode();
                result = (result*397) ^ Emission.GetHashCode();
                return result;
            }
        }
    }
}
